package se.teamscape.server.db;

import java.util.Date;
import java.util.List;

import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import se.teamscape.shared.model.Model;
import se.teamscape.shared.model.Person;
import se.teamscape.shared.model.Team;
import se.teamscape.shared.model.TeamPlayer;
import se.teamscape.shared.rpc.DBQuery;

/**
 * A Datastore implementation for Google App Engine datastore using JDO
 * entities.
 * 
 * @author Andreas Borglin
 * 
 */
public class GAEDatastore implements Datastore {

    public GAEDatastore() {
        // TODO: remove later
        createTestEntities();
    }

    @SuppressWarnings("unchecked")
    @Override
    public Model getModel(String encodedKey, String className) {

        System.out.println("GAE getModel");
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Model model = null;

        try {
            // TODO: Class.forName performance?
            Class cl = Class.forName(className);
            model = (Model) pm.getObjectById(cl, encodedKey);
            model = pm.detachCopy(model);
        }
        catch (JDOException e) {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        finally {
            pm.close();
        }

        return model;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Model> getModelsByQuery(DBQuery dbQuery) {

        System.out.println("GAE getModelsByQuery");
        PersistenceManager pm = PMF.get().getPersistenceManager();
        String queryString = dbQuery.toString();
        System.out.println("query: " + queryString);
        List<Model> results = null;

        try {
            Query query = pm.newQuery(queryString);

            if (dbQuery.getParamValues() != null)
                results = (List<Model>) query.executeWithArray(dbQuery.getParamValues().toArray());
            else
                results = (List<Model>) query.execute();

            results = (List<Model>) pm.detachCopyAll(results);
        }
        catch (JDOException e) {
            e.printStackTrace();
        }
        finally {
            pm.close();
        }

        return results;
    }

    @Override
    public Model saveModel(Model model) {

        System.out.println("GAE saveModel");
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Model savedModel = null;

        try {
            savedModel = pm.makePersistent(model);
        }
        catch (JDOException e) {
            e.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            pm.close();
        }

        return savedModel;
    }

    @Override
    public void createTestEntities() {

        DBQuery query = DBQuery.selectFrom(Team.class.getName());
        List<Model> models = getModelsByQuery(query);

        // only add test stuff if not already done
        if (models.size() != 0)
            return;

        System.out.println("createTestEntities");
        Person person = new Person();
        person.setFirstName("John");
        person.setLastName("Doe");
        person.setEmail("john.doe@db.com");
        person.setPhone("+123456789");
        person.setBirthday(new Date());
        person.setAdminLevel(0);
        person.setPassword("tempPw");

        Person savedPerson = (Person) saveModel(person);

        Team team = new Team();
        team.setName("The testers");
        team.setOwnerPersonKey(savedPerson.getId());
        Team savedTeam = (Team) saveModel(team);

        TeamPlayer player = new TeamPlayer();
        player.setPersonKey(savedPerson.getId());
        player.setTeamKey(savedTeam.getId());
        player.setPersonName(person.toString());
        player.setActive(true);
        player.setJoinDate(new Date());
        player.setPosition("Forward");
        player.setShirtNumber("99");
        player.setOtherInfo("Test player");
        saveModel(player);
    }

}
